<?php
class User_User extends ActiveRecord {

	protected static $_tableName = 'user';
	protected static $_pkName = 'ID_user';
	protected static $_essenceType = 2;
	
	public $isCaptchaCheck = true;

	public $arrImageSizes = array(
	  array(
	    'width' => 50,
	    'height' => 50,
	    'alias' => 'small',
	    'is_main' => true
	  ),
	  array(
	    'width' => 100,
	    'height' => 100,
	    'alias' => 'medium'
	  )
	);
	protected $arrSettings = array('created_at' => true,  // в БД храним время создания
																 'updated_at' => true, 	// в БД храним время редактирования
																 'image' => true);			// в БД храним аватар (не забываем про атрибут класса image)
	
	protected $availableFields = array(
		'ID_user', 
		'first_name', 
		'last_name', 
		'ID_country', 
		'city', 
		'address', 
		'zip',
		'home_phone',
		'age', 
		'login', 
		'e_mail' => 'create', 
		'pass' => 'create', 
		'pass_confirmation' => 'create', 
		'kaptcha' => 'create'
	);

  public function __construct($arrInitialFields = null) {
    Service_Debug::setDebug();
		parent::__construct($arrInitialFields);
		/*
		$this->validatesLengthOf = array(
		  'first_name' => array('minimum' => 2, 'maximum' => 128, 'message' => Service_Translate::getText('Имя должно состоять из 2-128 символов')),
		  'pass' => array('minimum' => 6, 'maximum' => 128, 'message' => Service_Translate::getText('Пароль введен неверно, должен состоять из 6-128 символов'), 'on' => 'create'),
			'home_phone' => array('minimum' => 8, 'maximum' => 24, 'message' => Service_Translate::getText('Телефон может содержать 8-24 символа'), 'on' => 'update', 'allowNull' => true),
			'zip' => array('minimum' => 2, 'maximum' => 12, 'message' => Service_Translate::getText('Индекс может содержать 2-16 символов'), 'on' => 'update', 'allowNull' => true),
		);
    $this->validatesFormatOf = array(
      'e_mail' => array('message' => Service_Translate::getText('Электронная почта заполнена неверно'), 
      'with' => '|^[\.\-_A-Za-z0-9]+?@[\.\-A-Za-z0-9]+?\.[A-Za-z0-9]{2,6}$|'
		));
    $this->validatesUniquenessOf = array(
      'e_mail' => array('message' => Service_Translate::getText('Эта электронная почта уже используется')),
	  );
	  $this->validatesConfirmationOf = array(
	    'pass' => array('message' => Service_Translate::getText('Пароль и его подтверждение не совпадают'), 'on' => 'create')
	  );
	  $this->validatesAcceptanceOf = array(
	    'confirm' => array('message' => Service_Translate::getText('Вы должны быть согласны с условиями'), 'on' => 'create')
	  );
	  $this->validatesAssociated = array(
      'ID_country' => array('class' => 'Country', 'message' => Service_Translate::getText('Необходимо выбрать страну'), 'on' => 'update')
    );
     */
  }
  
  /**
   * Метод вызывается перед регистрацией пользователя
   */
	public function beforeValidationOnCreate () {	
   	/*
   	if (isset($_GET['partner'])) $this->validatesLengthOf['login'] = array('minimum' => 4, 'maximum' => 64, 'message' => Service_Translate::getText('Логин должен состоять из 4-64 символов'));
    $objSession = User_Session::instance();
    if (!empty($this->tableFields['login'])) {
    	$login = Service_Escape::absolutelyEscapeString($this->tableFields['login']);
    	if (!$this->isLoginCorrect($login)) Exception_ActiveRecord::addObjectException(get_class($this), 'login', Service_Translate::getText('В логине допустимы символы a-z и 0-9'));
    	if ($this->isLoginExist($login)) Exception_ActiveRecord::addObjectException(get_class($this), 'login', Service_Translate::getText('Такой логин уже есть'));
    }
    if ($this->isCaptchaCheck && (!isset($this->tableFields['kaptcha']) || empty($this->tableFields['kaptcha']) || ($objSession->__get('keystring')!=$this->tableFields['kaptcha']))) {
    	$error = Service_Translate::getText('Неверный код подтверждения');
      Exception_ActiveRecord::addObjectException(get_class($this), 'kaptcha', $error);
    }
    */
	}
	
  /**
   * (non-PHPdoc)
   * @see ActiveRecord::beforeCreate()
   */
	public function beforeCreate() {
    /*
    if (isset($this->tableFields['kaptcha'])) unset($this->tableFields['kaptcha']);
    $this->tableFields['approve_code'] = md5(Service_Generate::generateWord(20)); //код для подтверждения регистрации
    $this->tableFields['pass'] = md5($this->tableFields['pass']);
    */
  }
  
  public function beforeValidationOnUpdate()
  {
  	if (!empty($this->tableFields['ID_user_topclient']))
  	{
  		 $this->availableFields['pass'] = '';  		 
  		 $this->availableFields['ID_user_topclient'] = '';
  		 $this->availableFields['ID_company'] = '';
  		 $this->availableFields['user_role'] = '';
  	}
  }

  /**
   * Метод проверяет, корректно ли введен адрес электроноой почты
   *
   * @param string $strEMail - e-mail
   */
  public static function isLoginCorrect($strLogin) {
    return preg_match("/^[A-Za-z0-9_]{3,32}$/", $strLogin);
  }

	/**
	 * Функция проверяет, существует ли данный EMail в БД
	 *
	 * @param $strEMail - строковое представление EMail
	 * @return true (если EMail присутствует в БД) или false
	 */
  public static function isEMailExist($strEMail) {
    Service_Debug::setDebug();
  	    return (self::getUserIdByEMail($strEMail)) ? true : false;  //Осуществляем SQL-запрос
  }
  
	/**
	 * Функция получает идентификатор пользователя по его eMail
	 *
	 * @param string $strEMail - строковое представление EMail
	 * @return int 
	 */
  public static function getUserIdByEMail($strEMail) {
    	$objDB = Service_Database::instance();//Получаем подключение к БД
    $stmt = "SELECT `ID_user` FROM `user` WHERE `e_mail` = '" . $strEMail . "'";  //формируем SQL-запрос
    return $objDB->selectSimpleField($stmt);
  }
	/**
	 * Функция получает идентификатор пользователя по его идентификатору VK
	 *
	 * @param int $vkId - идентификатор VK
	 * @return int 
	 */
  public static function getUserIdByVkId($vkId) {
    	$objDB = Service_Database::instance();//Получаем подключение к БД
    $stmt = "SELECT `ID_user` FROM `user` WHERE `ID_vk` = '" . $vkId . "'";  //формируем SQL-запрос
    return $objDB->selectSimpleField($stmt);
  }
	/**
	 * Функция получает идентификатор пользователя по его идентификатору FB
	 *
	 * @param int $fbId - идентификатор FB
	 * @return int 
	 */
  public static function getUserIdByFbId($fbId) {
    $objDB = Service_Database::instance();//Получаем подключение к БД
    $stmt = "SELECT `ID_user` FROM `user` WHERE `ID_fb` = '" . $fbId . "'";  //формируем SQL-запрос
    return $objDB->selectSimpleField($stmt);
  }
  
	/**
	 * Функция получает идентификатор пользователя по его идентификатору G+
	 *
	 * @param int $googlePlusId - идентификатор Google Plus
	 * @return int 
	 */
  public static function getUserIdByGooglePlusId($googlePlusId) {
    $objDB = Service_Database::instance(); //Получаем подключение к БД
    $stmt = "SELECT `ID_user` FROM `user` WHERE `ID_google_plus` = '" . $googlePlusId . "'";  //формируем SQL-запрос
    return $objDB->selectSimpleField($stmt);
  }

	/**
	 * Функция проверяет, существует ли данный EMail в БД
	 *
	 * @param $strEMail - строковое представление EMail
	 * @return true (если EMail присутствует в БД) или false
	 */
  public static function isLoginExist($login) {
    $objDB = Service_Database::instance();//Получаем подключение к БД
    $stmt = "SELECT `ID_user` FROM `user` WHERE `login` = '" . $login . "'";  //формируем SQL-запрос
    return (sizeof($objDB->select($stmt)) > 0) ? true : false;  //Осуществляем SQL-запрос
  }

	/**
	 * Устанавливает время последнего входа
	 */
	public static function setLoginTime() {
	  Service_Debug::setDebug();
		$objSession = User_Session::instance();
		$userId = $objSession->getUserId();
		if (!$userId) return null;
		$objDB = Service_Database::instance();//Получаем подключение к БД
	  $stmt = "UPDATE `user`
    				 SET  `login_time` = '" . Service_Date::gLocalTime2BD() . "'
    				 WHERE `user`.`ID_user` = '" . $userId . "'";
		return $objDB->query($stmt);
	}


	/**
	 * Устанавливает статус присутствия пользователя на сайте
	 *
	 * @param $status - статус пользователя
	 * @param $userId - id пользователя
	 */
	public static function setStatus($status, $userId) {
	  Service_Debug::setDebug();
		$objDB = Service_Database::instance();//Получаем подключение к БД
		$objSession = User_Session::instance();
		if (!$userId) $userId = $objSession->getUserId();
		if (!$userId) return null;
	  $stmt = "UPDATE `user`
    				 SET  `user_status` = '" . $status . "'
    				 WHERE `user`.`ID_user` = '" . $userId . "'";
	  return $objDB->query($stmt);
	}

	/**
	 * Метод устанавливает нулевой статус всем пользователям, которые не присутствуют на сайте уже 15 минут
	 */
	public static function setZeroStatusByTimeOut() {
	  Service_Debug::setDebug();
		$objDB = Service_Database::instance();//Получаем подключение к БД
		$stmt ="
		UPDATE `user`
    LEFT JOIN `session` ON `session`.`ID_user` = `user`.`ID_user`
    SET  `user_status` = 0
    WHERE (`session`.`last_impression` IS NULL) OR (`session`.`last_impression` < DATE_SUB(now(), INTERVAL 15 MINUTE));";
		return $objDB->query($stmt);
	}

	/**
	 * получение id пользователя по логину
	 *
	 * @param $login - логин пользователя
	 * @return id пользователя
	 */
	public static function getIdByLogin($login) {
	  Service_Debug::setDebug();
		$objDB = Service_Database::instance();//Получаем подключение к БД
		$stmt = "SELECT `ID_user` FROM `user` WHERE `login`='" . $login . "'";
		return $objDB->selectSimpleField($stmt);
	}

	/**
	 * Получает id пользователя
	 *
	 * @return integer id пользователя
	 */
	public static function getId() {
	  Service_Debug::setDebug();
		$objSesion = User_Session::instance();
		return $objSesion->getUserId();
	}



  /**
   * получаем логин по id
   *
   * @param integer $userId - id пользователя
   * @return string догин пользователя
   */
	public static function getUserLogin($userId) {
	  Service_Debug::setDebug();
		$objDB = Service_Database::instance();//Получаем подключение к БД
		$stmt ="SELECT `login` FROM `user` WHERE `ID_user`='" . $userId . "'";
		return $objDB->selectSimpleField($stmt);
	}

  /**
   * проверяем, существует ли пользователь с таким ID
   *
   * @param integer $userId - id пользователя
   * @return bool 
   */
	public static function isUserIdExists($userId) {
	  Service_Debug::setDebug();
		$objDB = Service_Database::instance();//Получаем подключение к БД
		$stmt ="SELECT `ID_user` FROM `user` WHERE `ID_user`='" . $userId . "'";
		return $objDB->isRecordExist($stmt);
	}

	/**
	 * Получаем логин по e-mail
	 *
	 * @param string $strEMail - e-mail
	 * @return string догин пользователя
	 */
	public static function getUserLoginByEmail($strEMail) {
	  Service_Debug::setDebug();
		$objDB = Service_Database::instance();//Получаем подключение к БД
		$stmt ="SELECT `login` FROM `user` WHERE `e_mail`='" . $strEMail . "'";
		return $objDB->selectSimpleField($stmt);
	}

	/**
	 * Получаем e-mail по id
	 *
	 * @param string $idUser - id пользователя
	 * @return string e-mail
	 */
	public static function getUserEmail($idUser) {
	  Service_Debug::setDebug();
		$objDB = Service_Database::instance();//Получаем подключение к БД
		$stmt ="SELECT `e_mail` FROM `user` WHERE `ID_user`='" . $idUser . "'";
		return $objDB->selectSimpleField($stmt);
	}

	/**
	 * Возварщает объект текущего пользователя
	 */
	public static function getUser() {
	  Service_Debug::setDebug();
	  $objSession = User_Session::instance();
	  return $objSession->getUser();
	}
	

	
	
	
	/**
	 * Добавляет пользователя в систему
	 * 
	 */
	public function signUpUser() {
		if (!$this->getField('login') || !$this->getField('e_mail')) return false;
		
		if (!$this->isLoginCorrect($this->getField('login'))) throw new Exception('Логин заполнен неправильно - допускаются только латинские буквы и цифры');
		if (!Service_Mail::isEMailCorrect($this->getField('e_mail'))) throw new Exception('Адрес электронной почты заполнен неверно');
		if ($this->isLoginExist($this->getField('login'))) throw new Exception('Пользователь с таким логином уже существует');
		if ($this->isEMailExist($this->getField('e_mail'))) throw new Exception('Пользователь с таким адресом электронной почты уже существует');

		
		$objDB = Service_Database::instance();//Получаем подключение к БД
		if (!$this->getField('pass')) {
			$this->setField('pass', Service_Generate::generatePassword());
		} 
		$stmt ="INSERT INTO `user` (`login`, `e_mail`, `pass`)
		VALUES ('" . $this->getField('login') . "', '" . $this->getField('e_mail') . "', '" . md5($this->getField('pass')) . "');";
		$this->id = $objDB->queryInsertAutoincrement($stmt);
		$this->setField('ID_user', $this->id);
		
		$objNotification = new User_Notification();
		$objNotification->newAccount($this->getField('e_mail'), $this->getField('login'), $this->getField('pass'), View_User::getUserName($this->tableFields));
		
		return $this->id;
	}
	
	/**
	 * Создает папку для аватарок пользователя, если ее еще нет
	 * 
	 * @param int $userId - идентификатор пользователя
	 */
	public static function createUserImagesFolderIfNecessary($userId) {
		if (!$userId) return false;
		$usersFolder = IMAGES . 'essence/user/';
		if(!is_dir($usersFolder . $userId)) mkdir($usersFolder . $userId, 0700);
	}
	
	/**
	 * Метод получает данные о пользователе для API
	 * 
	 * @return array - массив данных о пользователе
	 */
	public function getUserDataForApi() {
		if (!$this->id) return array();
		$arrRet = array();
		$arrFieldsToCopy = array('ID_user', 'e_mail', 'login', 'ID_vk', 'ID_fb', 'ID_google_plus', 'first_name', 'last_name', 'home_phone', 'city', 'ID_country');
		foreach ($arrFieldsToCopy as $fieldName) {
			$arrRet[$fieldName] = $this->getField($fieldName);
		}
		if(!empty($arrRet['home_phone'])) $arrRet['home_phone'] = Phone::make($arrRet['home_phone'])->get()->phone;
		return $arrRet;
	}
	
	/**
	 * Метод регистрирует юзера по почту и имени
	 * @param string $email - почта
	 * @param string $userName - имя пользователя. Если в нем есть пробел, то оно разбивается на имя и фамилию
	 */
	public static function regUser($email, $userName, $sendMessage = true) {
		if (!Service_Mail::isEMailCorrect($email) || User_User::isEMailExist($email)) return false;
		$pass = Service_Generate::generatePassword();
		$arrFields = array('e_mail' => $email, 'pass' => md5($pass), 'created_at' => Service_Date::gLocalTime2BD());
		$arrNames = explode(' ', $userName);
		$arrFields['first_name'] = $arrNames[0];
		if (!empty($arrNames[1])) $arrFields['last_name'] = $arrNames[1];
		if (!empty($arrNames[2])) $arrFields['middle_name'] = $arrNames[2];
		
		$objDB = Service_Database::instance();
		$userId = $objDB->insertAutoincrement('user', $arrFields);
		
		if ($sendMessage)
		{
			$objNotification = new User_Notification();
			$objNotification->newAccount($email, null, $pass, $userName);
		}
		
		
		return $userId;
	}
	
	/**
	 * Сохраняем реферала
	 * @see ActiveRecord::afterCreate()
	 */
	protected function afterCreate() {
		if (!empty($_COOKIE['link'])) {
			$objUser = new User_User();
			$objUser->find('first', array(
				'conditions' => "`login` = '" . Service_Escape::absolutelyEscapeString($_COOKIE['link']) . "'",
			));
			
			if ($objUser->id) $this->updateField('ID_parent_user', $objUser->id);
		}
	}
	
	/**
	 * (non-PHPdoc)
	 * @see ActiveRecord::afterSave()
	 */
	protected function afterSave() {
		if (!empty($_FILES['avatar']['name'])) $this->saveAvatar($_FILES['avatar']);
	}	

	/**
	 * Сохранение изображения
	 *
	 * @param mixed $file - картинка из $_FILES
	 */
	public function saveAvatar($file) {
		$objImage = new Service_Image(array(
			'resizeType' => 'crop',
			'availableExtensions' => array('jpg'),
			'throw' => true,
			'usePrefix' => true,
			'exception' => true
		));
		$ourPhotoId = $this->id * 100 + $this->getEssenceType();
		$objImage->setGoalFolder('essence/user/');
		if (is_array($file)) $objImage->loadScrAsArray($file);
		else $objImage->loadScrAsFile($file);
		$objImage->setGoalName($ourPhotoId);
		$objImage->saveExistingFile();
		$objImage->save();
		$urlPhotoId = $ourPhotoId * 100 + Extranet_Hotel::getSystemTypeId();
		$this->updateField('ID_photo', $urlPhotoId);
		// Удаляем старую кэшированную картинку
		$filePath = IMAGES . 'hotel_static/user60x60/' . substr($urlPhotoId, 0, 3) . '/' . $urlPhotoId . '.png';
		if (is_file($filePath)) unlink($filePath);
	}
	
	/**
	 * Метод возвращает текущий баланс пользователя-партнера
	 * @param bool $getAllBalance - показать баланс за все время (без учета списываний за выплаты)
	 * @param bool $isDurring - вычитывать из баланса те выплаты, у которых статус "в процессе"
	 */
	public function getPartnerBalance($getAllBalance = false, $isDurring = false) {
		if (!$this->getField('login')) return 0;
		$objDB = Service_Database::instance();
		
		// Все приходы
		$stmt = "SELECT SUM(`sum`) `sum`
				FROM `partner_receipt`
				INNER JOIN `booking` USING(`ID_booking`)
				INNER JOIN `user` ON `user`.`ID_user` = `booking`.`ID_user`
				WHERE `partner_receipt`.`ID_user` ='" . $this->id . "' AND `is_admin` = 0";
		$balance = $objDB->selectSimpleField($stmt);
		if(!$balance) $balance = 0;

		// Все выплаты
		if (!$getAllBalance) {
			$objDB = Service_Database::instance();
			$stmt = "SELECT SUM(`balance`) FROM `partner_payment` WHERE `ID_user` = " . $this->id . " AND `status` " . ($isDurring ? 'IN (0, 1)' : '= 1');
			$paymentBalance = $objDB->selectSimpleField($stmt);
		}
		else $paymentBalance = 0;
		
		return round($balance - $paymentBalance, 2);
	}
	
	/**
	 * Сохраняет Аватарку из URL
	 * 
	 * @param string $url - URL файла с картинкой
	 */
	public function saveAvatarFromUrl($url) {
		$data = @file_get_contents($url);
		if (!$data) return false;
		$file = TMP . $this->id . time() . '.jpg';
		$fp = fopen($file, 'w');
		fwrite($fp, $data);
		fclose($fp);
		
		try {
			$this->saveAvatar($file);
		}
		catch (Exception $e) {
			
		}
		unlink($file);
	}
	
	
}
?>